package com.yong.android.framework.view.recyclerview.extra;

import android.support.annotation.IntRange;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.yong.android.framework.view.recyclerview.RecyclerViewCell;


/**
 * Description:
 * Author:yong
 * Date:2017-12-21
 */

public abstract class ExpandableListCell<VH extends RecyclerView.ViewHolder> extends RecyclerViewCell<VH> {

    @Override
    protected final VH onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) {
        if (viewType >> 5 == 3) {
            return onCreateGroupViewHolder(inflater, parent, viewType & 0x1f);
        } else if (viewType >> 5 == 2) {
            return onCreateChildViewHolder(inflater, parent, viewType & 0x1f);
        }
        return null;
    }

    @Override
    protected void onBindViewHolder(VH holder, int position) {
        int groupRealPosition = computeGroupRealPosition(position);
        int groupPosition = computeGroupPosition(position);
        if (position == groupRealPosition) {
            onBindGroupViewHolder(holder, groupPosition);
        } else {
            onBindChildViewHolder(holder, groupPosition, position - groupRealPosition - 1);
        }
    }

    protected abstract VH onCreateGroupViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType);

    protected abstract VH onCreateChildViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType);

    protected abstract void onBindGroupViewHolder(VH holder, int groupPosition);

    protected abstract void onBindChildViewHolder(VH holder, int groupPosition, int childPosition);

    @Override
    public final int getItemViewType(int position) {
        int groupRealPosition = computeGroupRealPosition(position);
        int groupPosition = computeGroupPosition(position);
        if (position == groupRealPosition) {
            int gViewType = getGroupViewType(groupPosition);
            return gViewType < 0 ? -(Math.abs(gViewType) + (3 << 5)) : gViewType + (3 << 5);
        } else {
            int cViewType = getChildViewType(groupPosition, position - groupRealPosition - 1);
            return cViewType < 0 ? -(Math.abs(cViewType) + (1 << 6)) : cViewType + (1 << 6);
        }

    }

    @Override
    public final int getCount() {
        if (getGroupCount() == 0) {
            return 0;
        }
        int totalCount = 0;
        for (int i = 0, total = getGroupCount(); i < total; i++) {
            totalCount += (1 + getChildCount(i));
        }
        return totalCount;
    }

    @IntRange(from = -31, to = 31)
    public int getGroupViewType(int groupPosition) {
        return 0;
    }

    @IntRange(from = -31, to = 31)
    public int getChildViewType(int groupPosition, int childPosition) {
        return 0;
    }

    public abstract int getGroupCount();

    public abstract int getChildCount(int groupPosition);

    private int computeGroupRealPosition(int realPosition) {
        if (getGroupCount() == 0) {
            return -1;
        }
        if (realPosition == 0) {
            return 0;
        }
        int lv = 0;
        int rv = 0;
        for (int i = 0, total = getGroupCount(); i < total; i++) {
            lv = rv;
            rv = lv + getChildCount(i) + 1;
            if (realPosition < rv) {
                return lv;
            }

        }
        return rv;
    }

    private int computeGroupPosition(int realPosition) {
        if (getGroupCount() == 0) {
            return -1;
        }
        if (realPosition == 0) {
            return 0;
        }
        int lv = 0;
        int rv = 0;
        for (int i = 0, total = getGroupCount(); i < total; i++) {
            lv = rv;
            rv = lv + getChildCount(i) + 1;
            if (realPosition < rv) {
                return i;
            }
        }
        return getGroupCount() - 1;
    }
}
